﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="Knife.cs" company="">
//   
// </copyright>
// <summary>
// A weapon that the player only can use near to him. 
// </summary>
// --------------------------------------------------------------------------------------------------------------------

/*
 * Author: Barbara Carboni
 * Created: 17-11-2011
 */

namespace ITU_vs_Zombies.Stuff
{
    using System;
    using System.Diagnostics.Contracts;
    using System.Linq;

    using ITU_vs_Zombies.Character;
    using ITU_vs_Zombies.Game;
    using ITU_vs_Zombies.Movement;
    using ITU_vs_Zombies.Scenery;

    using Microsoft.Xna.Framework;

    /// <summary>
    /// A weapon that the player only can use near to him. 
    /// </summary>
    [Serializable]
    public class Knife : Weapon
    {
        #region Constants and Fields

        /// <summary>
        /// The distance.
        /// </summary>
        private uint distance;

        #endregion

        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="Knife"/> class.
        /// </summary>
        /// <param name="image">
        /// The Image. 
        /// </param>
        /// <param name="numberFrames">
        /// The number of frames. 
        /// </param>
        /// <param name="numberFloor">
        /// The number of floor. 
        /// </param>
        /// <param name="position">
        /// The position. 
        /// </param>
        /// <param name="damage">
        /// The damage. 
        /// </param>
        /// <param name="distance">
        /// The distance. 
        /// </param>
        /// <param name="sound">
        /// The sound. 
        /// </param>
        public Knife(
            string image, uint numberFrames, int numberFloor, Vector2 position, uint damage, uint distance, string sound)
            : base(image, numberFrames, numberFloor, position, damage, new TimeSpan(0), sound)
        {
            Contract.Requires(image != null);
            Contract.Requires(sound != null);
            Contract.Requires(distance > 0);
            Contract.Requires(damage > 0);
            Contract.Requires(numberFrames > 0);
            Contract.Requires(position.X >= 0 && position.Y >= 0);
            this.Distance = distance;
        }

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets the distance.
        /// </summary>
        public uint Distance
        {
            get
            {
                Contract.Ensures(Contract.Result<uint>() > 0);
                return this.distance;
            }

            private set
            {
                Contract.Requires(value > 0);
                this.distance = value;
            }
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// The clone.
        /// </summary>
        /// <returns>
        /// The clone.
        /// </returns>
        public override object Clone()
        {
            var knife = (Knife)base.Clone();
            knife.Distance = this.Distance;
            return knife;
        }

        /// <summary>
        /// The shoot.
        /// </summary>
        /// <param name="gameTime">
        /// The game Time.
        /// </param>
        /// <param name="position">
        /// The position.
        /// </param>
        /// <param name="direction">
        /// The direction.
        /// </param>
        public override void Use(GameTime gameTime, Vector2 position, MovementsEnum direction)
        {
            if (!this.CanUse(gameTime))
            {
                return;
            }

            this.Sound.Play();

            Floor floor = Client.Floors.Find(f => this.NumberFloor == f.Number);
            foreach (
                Enemy enemy in
                    floor.EnemiesNear(Client.MainPlayer, direction, this.Distance).Where(enemy => enemy.Life > 0))
            {
                enemy.Life -= this.Damage <= enemy.Life ? this.Damage : enemy.Life;
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// The can use.
        /// </summary>
        /// <param name="gameTime">
        /// The game time.
        /// </param>
        /// <returns>
        /// The can use.
        /// </returns>
        protected override bool CanUse(GameTime gameTime)
        {
            return true;
        }

        #endregion
    }
}